package net.huashitong.ssydt.provider.web.exception;

import net.huashitong.ssydt.exceptions.ServiceException;
import net.huashitong.ssydt.provider.security.exceptions.LoginRequiredException;
import net.huashitong.ssydt.provider.security.exceptions.LoginElsewhereException;
import net.huashitong.ssydt.provider.security.exceptions.LoginoutException;
import net.huashitong.ssydt.provider.security.exceptions.OvertimeException;
import net.huashitong.ssydt.provider.security.exceptions.ParamErrorException;
import net.huashitong.ssydt.provider.utils.StringUtils;
import net.huashitong.ssydt.provider.web.model.Result;
import net.huashitong.ssydt.provider.web.utils.ResultUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 自定义统一异常处理
 *
 * @author huiyang.yu
 */
@RestControllerAdvice
public class DefaultExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @ExceptionHandler({LoginRequiredException.class})
    public Result<String> processLoginRequiredException(LoginRequiredException exception) {
        String code = Result.Status.LOGINOUT;
        if (exception instanceof ParamErrorException) {
            code = Result.Status.PARAM_ERROR;
        } else if (exception instanceof OvertimeException) {
            code = Result.Status.OVERTIME;
        } else if (exception instanceof LoginoutException) {
            code = Result.Status.LOGINOUT;
        } else if (exception instanceof LoginElsewhereException) {
            code = Result.Status.LOGIN_ELSEWHERE;
        }
        logger.info("LoginRequiredException，ExceptionCode:[{}] ExceptionMessage:[{}]", code, exception.getMessage());
        return ResultUtils.getResults(code, exception.getMessage());

    }

    @ExceptionHandler({ServiceException.class})
    public Result<String> processServiceException(ServiceException exception) {
        if (StringUtils.isNotBlank(exception.getCode())) {
            logger.info("ServiceException， ExceptionMessage:[{}], Code:[{}]", exception.getMessage(), exception.getCode());
            return ResultUtils.getResults(exception.getCode(), exception.getMessage());
        } else {
            logger.info("ServiceException， ExceptionMessage:[{}]", exception.getMessage());
            return ResultUtils.getResults(Result.Status.ERROR, exception.getMessage());
        }
    }

    @ExceptionHandler({RuntimeException.class})
    public Result<String> processRuntimeException(RuntimeException exception) {
        logger.error("RuntimeException : ", exception);
        return ResultUtils.getResults(Result.Status.ERROR, exception.getMessage());

    }

    @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
    public Result<String> bindException(Exception exception) {
        BindingResult result;
        if (exception instanceof BindException) {
            BindException thisException = (BindException) exception;
            result = thisException.getBindingResult();
        } else {
            MethodArgumentNotValidException thisException = (MethodArgumentNotValidException) exception;
            result = thisException.getBindingResult();
        }

        List<FieldError> list = result.getFieldErrors();
        StringBuilder msg = new StringBuilder();
        for (FieldError fieldError : list) {
            logger.debug("objectName [{}] field [{}] rejectedValue [{}]",
                    fieldError.getObjectName(),
                    fieldError.getField(),
                    fieldError.getRejectedValue());
            msg.append(fieldError.getDefaultMessage()).append(";");
        }
        String message = msg.toString();
        logger.info("{}, ExceptionMessage:[{}]", exception.getClass().getSimpleName(), message);
        return ResultUtils.getResults(Result.Status.PARAM_ERROR, message);
    }

}
